package logic

import (
	"fmt"
	"github.com/chenwbyx/leafserver/server/game"
	"github.com/chenwbyx/leafserver/server/models/rpcm"
	"github.com/chenwbyx/leafserver/server/msg/client"
	"github.com/chenwbyx/leafserver/server/pkg/e"
	"github.com/chenwbyx/leafserver/server/pkg/gredis"
	"github.com/chenwbyx/leafserver/server/pkg/logging"
	"github.com/chenwbyx/leafserver/server/pkg/util"
	"github.com/name5566/leaf/gate"
	"go.uber.org/zap"
	"log"
	"regexp"
	"time"
)

func HandleUserRegister(args []interface{}) {
	m := args[0].(*client.UserRegisterReq)
	a := args[1].(gate.Agent)
	name := m.GetLoginName()
	pwd := m.GetLoginPW()
	logging.LoginLogger.Debugln("receive UserRegister", zap.String("LoginName", m.GetLoginName()))

	reg := regexp.MustCompile(`/^[a-zA-Z\d]\w{2,10}[a-zA-Z\d]$/`)
	matched := reg.FindString(name)
	if matched != " " {
		logging.LoginLogger.Debugln("UserRegister name is licit")
	}
	ok, err := rpcm.GetLoginByName(name)
	if err != nil {
		log.Println(err)
	}
	if ok == true {
		logging.LoginLogger.Debugln("UserRegister find in fail")

		retBuf := &client.DefaultReault{
			RetResult: e.ACCOUNT_EXIST,
			ErrorInfo: e.GetMsg(e.ACCOUNT_EXIST),
		}

		a.WriteMsg(retBuf)
	}
	err = rpcm.AddLogin(name, pwd)
	if err != nil {
		log.Println(err)
		logging.LoginLogger.Debugln("UserRegister write in fail")
		retBuf := &client.DefaultReault{
			RetResult: e.REGISTRE_FAIL,
			ErrorInfo: e.GetMsg(e.REGISTRE_FAIL),
		}
		a.WriteMsg(retBuf)
	} else {
		logging.LoginLogger.Debugln("UserRegister write in success")
		retBuf := &client.DefaultReault{
			RetResult: e.REGISTRE_SUCCESS,
		}

		a.WriteMsg(retBuf)
	}
}

func HandleUserLogin(args []interface{}) {
	m := args[0].(*client.UserLoginReq)
	a := args[1].(gate.Agent)
	name := m.GetLoginName()
	pwd := m.GetLoginPW()
	logging.LoginLogger.Debugln("receive UserRegister", name)
	claims, token, err := util.GenerateToken(name, pwd)
	if err != nil {
		logging.LoginLogger.Errorln("create token error ", err)
		return
	}
	key := fmt.Sprintf(gredis.UserToken, name)
	redisToken := gredis.Global_redis.Get(gredis.REDIS_USER, key)
	redisClaims, _ := util.ParseToken(redisToken.Val())

	retBuf := &client.DefaultReault{}

	if redisClaims != nil && (redisClaims.Username != claims.Username || redisClaims.Password != claims.Password) {
		if redisClaims.Username != claims.Username {
			logging.LoginLogger.Debugln("Username error")
			retBuf.RetResult = e.ACCOUNT_USER_ERROR
			retBuf.ErrorInfo = e.GetMsg(e.ACCOUNT_USER_ERROR)
			a.WriteMsg(retBuf)
			return
		}
		if redisClaims.Password != claims.Password {
			logging.LoginLogger.Debugln("Password error")
			retBuf.RetResult = e.ACCOUNT_PWD_ERROR
			retBuf.ErrorInfo = e.GetMsg(e.ACCOUNT_PWD_ERROR)
			a.WriteMsg(retBuf)
			return
		}
	}

	if redisToken.Val() == token {
		retBuf.RetResult = e.LOGIN_SUCCESS
		retBuf.ErrorInfo = e.GetMsg(e.LOGIN_SUCCESS)
		a.WriteMsg(retBuf)
		return
	}

	account := rpcm.GetAccountByName(name)
	if account == nil {
		newAccount := rpcm.CreatAccountByAccountIDAndPassword(name, pwd)
		if nil != newAccount {
			game.ChanRPC.Go("UserLogin", a, newAccount.UserID)
			retBuf.RetResult = e.LOGIN_SUCCESS
			retBuf.ErrorInfo = e.GetMsg(e.LOGIN_SUCCESS)
		} else {
			logging.LoginLogger.Debugln("create account error ", zap.String("LoginName", name))
			retBuf.RetResult = e.LOGIN_FAIL
			retBuf.ErrorInfo = e.GetMsg(e.LOGIN_FAIL)
		}
		a.WriteMsg(retBuf)
		return
	} else {
		if pwd == account.Password {
			gredis.Global_redis.Set(gredis.REDIS_USER, key, token, time.Hour*8)

			logging.LoginLogger.Debugln("UserLogin find in success", zap.String("token", token))
			retBuf.RetResult = e.LOGIN_SUCCESS
			retBuf.ErrorInfo = e.GetMsg(e.LOGIN_SUCCESS)
			a.WriteMsg(retBuf)
			return
		}
	}
}
